<?php

namespace addons\third\library;

use fast\Http;
use think\Config;
use think\Session;

/**
 * 微信
 */
class Wechat
{
    const GET_AUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
    const GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    const GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
    const GET_WX_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/jscode2session";
    /**
     * 配置信息
     * @var array
     */
    private $config = [];

    public function __construct($options = [])
    {
        if ($config = Config::get('third.wechat')) {
            $this->config = array_merge($this->config, $config);
        }
        $this->config = array_merge($this->config, is_array($options) ? $options : []);
    }

    /**
     * 登陆
     */
    public function login()
    {
        header("Location:" . $this->getAuthorizeUrl());
    }

    /**
     * 获取authorize_url
     */
    public function getAuthorizeUrl()
    {
        $state = md5(uniqid(rand(), true));
        Session::set('state', $state);
        $queryarr = array(
            "appid"         => $this->config['app_id'],
            "redirect_uri"  => $this->config['callback'],
            "response_type" => "code",
            "scope"         => $this->config['scope'],
            "state"         => $state,
        );
        request()->isMobile() && $queryarr['display'] = 'mobile';
        $url = self::GET_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#wechat_redirect';
        return $url;
    }

    /**
     * 获取用户信息
     * @param array $params
     * @return array
     */
    public function getUserInfo($params = [])
    {
        $params = $params ? $params : request()->get();
        if (isset($params['code']) || isset($params['access_token']) || (isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) {
            //获取access_token
            $data = isset($params['code']) ? $this->getJsAccessToken($params['code']) : $params;
    
            $access_token = isset($data['access_token']) ? $data['access_token'] : $data['session_key'];
            $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
            $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0;
            if ($access_token) {
                $openid = isset($data['openid']) ? $data['openid'] : '';
                $unionid = isset($data['unionid']) ? $data['unionid'] : '';
//              if (stripos($this->config['scope'], 'snsapi_userinfo') !== false) {
//                  //获取用户信息
//                  $queryarr = [
//                      "access_token" => $access_token,
//                      "openid"       => $openid,
//                      "lang"         => 'zh_CN'
//                  ];
//                  $ret = Http::get(self::GET_USERINFO_URL, $queryarr);
//                  $userinfo = (array)json_decode($ret, true);
//                  return $userinfo;
//                  if (!$userinfo || isset($userinfo['errcode'])) {
//                      return [];
//                  }
//                  $userinfo = $userinfo ? $userinfo : [];
//                  $userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : '';
//              } else {
//                  $userinfo = [];
//              }
                $userinfo = [];
                $data = [
                    'access_token'  => $access_token,
                    'refresh_token' => $refresh_token,
                    'expires_in'    => $expires_in,
                    'openid'        => $openid,
                    'unionid'       => $unionid,
                    'userinfo'      => $userinfo
                ];
                return $data;
            }
        }
        return [];
    }

    /**
     * 获取access_token
     * @param string code
     * @return array
     */
    public function getAccessToken($code = '')
    {
        if (!$code) {
            return [];
        }
        $queryarr = array(
            "appid"      => $this->config['app_id'],
            "secret"     => $this->config['app_secret'],
            "code"       => $code,
            "grant_type" => "authorization_code",
        );
        $response = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr);
        $ret = (array)json_decode($response, true);
        return $ret ? $ret : [];
    }
    
        /**
     * 获取微信用户信息
     * @param array $params
     * @return array
     */
    public function getWxUserInfo($params = [])
    {
        $params = $params ? $params : request()->get();
        if (isset($params['access_token']) || isset($params['code'])) {
            //获取access_token
            $data = isset($params['code']) ? $this->getJsAccessToken($params['code']) : $params;
            
//          $data['session_key'] = 'VCzz+MwKHDTlw0SCgyGb0Q==';
//          $data['openid'] = 'oE0wp5MOhA2ujNweKkEELrUIm4hc';
            $access_token = isset($data['access_token']) ? $data['access_token'] : $data['session_key'];
            $refresh_token = isset($data['refresh_token']) ? $data['refresh_token'] : '';
            $expires_in = isset($data['expires_in']) ? $data['expires_in'] : 0; 
            if ($access_token) {
                $openid = isset($data['openid']) ? $data['openid'] : '';
                $unionid = isset($data['unionid']) ? $data['unionid'] : '';
//              if (stripos($this->config['scope'], 'snsapi_userinfo') !== false) {
//                  //获取用户信息
//                  $queryarr = [
//                      "access_token" => $access_token,
//                      "openid"       => $openid,
//                      "lang"         => 'zh_CN'
//                  ];
//                  $ret = Http::get(self::GET_USERINFO_URL, $queryarr);
//                  $userinfo = (array)json_decode($ret, true);
//                  if (!$userinfo || isset($userinfo['errcode'])) {
//                      return [];
//                  }
//                  $userinfo = $userinfo ? $userinfo : [];
//                  $userinfo['avatar'] = isset($userinfo['headimgurl']) ? $userinfo['headimgurl'] : '';
//              } else {
//                  $userinfo = [];
//              }

	            $iv = $params['iv'];
	            $encryptedData = $params['encryptedData'];
	            $encryptedData = urldecode($encryptedData);//再次编码解码一次防止有特殊字符，如果浏览器直接访问的话，这行要注释掉，浏览器会自动进行解码
	            $iv = urldecode($iv);//再次编码解码一次防止有特殊字符，
	            $iv = str_replace(' ', '+', $iv);//防止＋ 变成 空格
	            $encryptedData = str_replace(' ', '+', $encryptedData);
	            
	            $errCode = $this->decryptData($access_token, $this->config['app_id'], $encryptedData, $iv, $data);
	            //用sessionKey解密数据encryptedData
	            if ($errCode !== 0) {
	                return [];
	            }
	            $data = json_decode($data, true);//转成数组
	            
	            $data['phoneNumber'] = preg_replace('# #', '', $data['phoneNumber']);//去掉多个空格
                $data['phoneNumber'] = str_replace('+','',$data['phoneNumber']);

                $userinfo = isset($userinfo) ? $userinfo : [];
                $userinfo['username'] = $userinfo['nickname'] = $userinfo['mobile'] = isset($data['phoneNumber']) ? $data['phoneNumber'] : '';
              
                $data = [
                    'access_token'  => $access_token,
                    'refresh_token' => $refresh_token,
                    'expires_in'    => $expires_in,
                    'openid'        => $openid,
                    'unionid'       => $unionid,
                    'userinfo'      => $userinfo
                ];
                return $data;
            }
        }
        return [];
    }
        /**
     * 获取小程序授权access_token
     * @param string code
     * @return array
     */
    public function getJsAccessToken($code = '')
    {
        if (!$code) {
            return [];
        }
        $queryarr = array(
            "appid"      => $this->config['app_id'],
            "secret"     => $this->config['app_secret'],
            "js_code"       => $code,
            "grant_type" => "authorization_code",
        );
        $response = Http::get(self::GET_WX_ACCESS_TOKEN_URL, $queryarr);
        $ret = (array)json_decode($response, true);
        return $ret ? $ret : [];
    }
    
     /**
     * 检验数据的真实性，并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0，失败返回对应的错误码
     */
    public function decryptData($sessionKey, $appid, $encryptedData, $iv, &$data)
    {
        if (strlen($sessionKey) != 24) {
            return 'sessionKey 非法';
        }
        $aesKey = base64_decode($sessionKey);
        if (strlen($iv) != 24) {
            return 'iv 非法';
        }
        $aesIV = base64_decode($iv);
        $aesCipher = base64_decode($encryptedData);
        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
        $dataObj = json_decode($result);
        if ($dataObj == null) {
            return 'aes 解密失败';
        } else {
            if ($dataObj->watermark->appid != $appid) {
                return 'appid错误';
            }
        }
        $data = $result;
        return 0;
    }
    
}
